package cn.lzm.server.tcp;

import cn.hutool.core.util.IdUtil;
import cn.lizemin.entity.RpcRequest;
import cn.lizemin.entity.RpcResponse;
import cn.lzm.RpcApplication;
import cn.lzm.model.ServiceMetaInfo;
import cn.lzm.protocol.*;
import io.vertx.core.Vertx;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetSocket;

import java.io.IOException;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 * @author lzm
 * @Date 2024/11/5
 * @description
 */
public class VertxTcpRequestClient {

    /**
     * 发送请求
     *
     * @param serviceMetaInfo 服务节点信息
     * @param req  请求入参
     * @return
     * @throws InterruptedException
     * @throws ExecutionException
     */
    public static RpcResponse doRequest(ServiceMetaInfo serviceMetaInfo, RpcRequest req) throws InterruptedException, ExecutionException {
        Vertx vertx = Vertx.vertx();
        NetClient netClient = vertx.createNetClient();
        CompletableFuture<RpcResponse> future = new CompletableFuture<>();
        netClient.connect(serviceMetaInfo.getPort(), serviceMetaInfo.getHost(), result -> {
            if (result.succeeded()) {
                System.out.println("connect to tcp server success");
                ProtocolMessage.Header header = new ProtocolMessage.Header();
                header.setMagic(ProtocolConst.PROTOCOL_MAGIC);
                header.setVersion(ProtocolConst.PROTOCOL_VERSION);

                // 改为使用配置文件中定义的序列化方式
                String serializerName = RpcApplication.getRpcConfig().getSerializer();
                ProtocolMessageSerializerEnum serializerEnum = ProtocolMessageSerializerEnum.getSerializerByValue(serializerName);
                if (Objects.isNull(serializerEnum)) {
                    throw new RuntimeException("未找到指定的序列化器：" + serializerName);
                }
                header.setSerializer((byte) serializerEnum.getKey());
                header.setType((byte) ProtocolMessageTypeEnum.REQUEST.getKey());
                header.setStatus((byte) ProtocolStatusEnum.OK.getValue());
                header.setRequestId(IdUtil.getSnowflakeNextId());

                ProtocolMessage<RpcRequest> message = new ProtocolMessage<>(header, req);
                NetSocket socket = result.result();
                try {
                    Buffer encodeReq = ProtocolMessageEncoder.encode(message);
                    socket.write(encodeReq);
                } catch (IOException e) {
                    throw new RuntimeException("协议消息编码错误");
                }

                TcpBufferHandlerWrapper wrapper = new TcpBufferHandlerWrapper(buffer -> {
                    try {
                        ProtocolMessage<RpcResponse> respMessage = (ProtocolMessage<RpcResponse>) ProtocolMessageDecoder.decode(buffer);
                        RpcResponse response = respMessage.getBody();
                        future.complete(response);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                });
                socket.handler(wrapper);
            } else {
                System.err.println("failed to connect to tcp server");
            }
        });
        RpcResponse response = future.get();
        // 关闭连接
        netClient.close();
        return response;
    }

}
